﻿using System;
using System.Collections.Concurrent;

namespace QQ2564874169.Miniblink
{
    public class MiniblinkEventArgs : EventArgs
    {
        internal MiniblinkEventArgs() { }
    }

    public class UrlChangedEventArgs : MiniblinkEventArgs
    {
        public string Url { get; internal set; }

        internal UrlChangedEventArgs() { }
    }

    public class NavigateEventArgs : MiniblinkEventArgs
    {
        public string Url { get; internal set; }
        public wkeNavigationType Type { get; internal set; }
        public bool Cancel { get; set; }

        internal NavigateEventArgs() { }
    }

    public class DocumentReadyEventArgs : MiniblinkEventArgs
    {
		public bool IsMain { get; internal set; }
        internal DocumentReadyEventArgs() { }
    }

    public class ConsoleMessageEventArgs : MiniblinkEventArgs
    {
        public wkeConsoleLevel Level { get; internal set; }
        public string Message { get; internal set; }
        public string SourceName { get; internal set; }
        public int SourceLine { get; internal set; }
        public string StackTrace { get; internal set; }

        internal ConsoleMessageEventArgs() { }
    }

    public class NetResponseEventArgs : MiniblinkEventArgs
    {
        public string Url { get; internal set; }
        public IntPtr Job { get; internal set; }
        public bool Cancel { get; set; }
        public byte[] Data { get; set; }
        public string ContentType { get; set; }

        internal NetResponseEventArgs() { }
    }

    public class LoadUrlBeginEventArgs : MiniblinkEventArgs
    {
        private static ConcurrentDictionary<long, LoadUrlBeginEventArgs> _args = 
            new ConcurrentDictionary<long, LoadUrlBeginEventArgs>();

        public wkeRequestType RequestMethod { get; internal set; }
        public string Url { get; internal set; }
        public NetJob Job { get; internal set; }
        public byte[] Data { get; set; }
        public string ContentType { get; set; }
        public bool Cancel { get; set; }
        public bool IsLocalFile { get; internal set; }
        internal bool HookRequest { get; set; }
        private Action<LoadUrlEndArgs> _loadUrlEnd;
	    private object _endState;
	    internal bool Ended;

        internal LoadUrlBeginEventArgs() { }

	    public void WatchLoadUrlEnd(Action<LoadUrlEndArgs> callback, object state = null)
	    {
		    if (callback == null)
			    throw new ArgumentNullException(nameof(callback));

		    _loadUrlEnd = callback;
		    _endState = state;

		    if (HookRequest == false)
		    {
			    _args.TryAdd(Job.Handle.ToInt64(), this);

				HookRequest = true;
			}
	    }

	    internal LoadUrlEndArgs OnLoadUrlEnd(byte[] data)
		{
			Ended = true;

			if (HookRequest == false)
                return null;

			var e = new LoadUrlEndArgs
            {
                Data = data,
                Job = Job.Handle,
                RequestMethod = RequestMethod,
                Url = Url,
				State = _endState
            };
            _loadUrlEnd(e);

            return e;
        }

        internal static LoadUrlBeginEventArgs GetByJob(IntPtr job)
        {
            if (_args.ContainsKey(job.ToInt64()) == false)
                return null;
            LoadUrlBeginEventArgs e;
            return _args.TryRemove(job.ToInt64(), out e) ? e : null;
        }
    }

    public class LoadUrlEndArgs : MiniblinkEventArgs
    {
        public wkeRequestType RequestMethod { get; internal set; }
        public string Url { get; internal set; }
        public IntPtr Job { get; internal set; }
        public byte[] Data { get; internal set; }
		public object State { get; internal set; }
        internal bool Modify;

        internal LoadUrlEndArgs() { }

        public void ReplaceData(byte[] data)
        {
            Modify = true;
            Data = data;
        }
    }
}
